package com.sugo.seckill.aop;

import com.sugo.seckill.utils.ObjectUtils;
import com.sugo.seckill.distributedlock.redis.RedisLockUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * <p>redis同步锁实现类</p>
 * <pre>
 *      "@Order(param)"：param越小越是最先执行，但更重要的是最先执行的最后结束。order默认值是2147483647
 * </pre>
 * @author langxing
 * @date 2021/1/25 22:29
 */
@Component
@Scope
@Aspect
@Order(1)
public class RedisLockAspect {
    /**
     * Service层切点
     * 可以用于记录错误日志
     */
    @Pointcut("@annotation(com.sugo.seckill.aop.ServiceLock)")
    public void lockAspect() {}

    @Around("lockAspect()")
    public  Object around(ProceedingJoinPoint joinPoint) {
        Object obj = null;
        // 获取调用方法的第一个传参（商品ID）
        long seckillId = ObjectUtils.toLong(joinPoint.getArgs()[0]);
        String lockKey = "seckill_goods_lock_"+seckillId;
        RedisLockUtil.tryLock(lockKey, TimeUnit.SECONDS, 3, 10);
        try {
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
            throw new RuntimeException();
        } finally{
            RedisLockUtil.unlock(lockKey);
        }
        return obj;
    }
}
